#pragma once

#include "WHttpClientCommon.h"
#include "mongoose.h"

class WAsyncHttpClient;
struct HttpClientReqContext
{
    HttpClientCbFun cbFun;
    HttpClientReqMsg reqMsg;
    std::shared_ptr<HttpClientRspMsg> rspMsg;
    std::string url;
    WAsyncHttpClient *httpClient = nullptr;
    int64_t activeTime = 0;
    bool chunkFlag = false;
    mg_connection *conn;
};

class WAsyncHttpClient {
public:
    WAsyncHttpClient(mg_mgr *mgr = nullptr);
    virtual ~WAsyncHttpClient();

    // 发送 HTTP 请求并接收响应，目前这个只是普通消息处理，若想上传和下载文件，需要额外添加接口处理
    void sendRequest(std::string url, const HttpClientReqMsg& reqMsg, HttpClientCbFun cbFun);
    // 只支持带content-length的文件下载，不支持chunk流文件下载
    void sendRequestToDwFile(std::string url, const HttpClientReqMsg& reqMsg, HttpClientCbFun cbFun);
    bool run(int timeoutMs = 2);
    void setTimeout(int sec = 6);

private:
    struct mg_mgr *_mgr = nullptr;
    bool _selfMgrFlag = false;
    int _timeoutSec = 6;
    std::map<int64_t, HttpClientReqContext *> _fd2ContextMap;
    mg_timer _timer;

    void doSendRequset(std::string url, const HttpClientReqMsg& reqMsg, HttpClientCbFun cbFun, bool chunkFlag);
    std::string buildUrl(const std::string& uri, const std::map<std::string, std::string>& querys);
    std::string getIpFromDNS(const std::string &dnsStr, bool isIpv6First = false);
    void handleHttpClientEvent(mg_connection *conn, int msgType, void *msgData, void *cbData);
    std::shared_ptr<HttpClientRspMsg> parseHttpMsg(mg_connection *conn, struct mg_http_message *httpCbData, bool chunkFlag = false);
    void logHttpRequestMsg(mg_connection *conn, mg_http_message *httpCbData);
    uint64_t getSysTickCountInMilliseconds();
    void checkoutRequestTimeout();
    void handleNewChunkData(std::shared_ptr<HttpClientRspMsg> rspMsg, mg_connection *conn, mg_http_message *httpCbData);

    static void httpClientEventCb(mg_connection *conn, int msgType, void *msgData, void *cbData);
    static void timerEventAdapter(void *ptr);
};
